from utils.basic_function import *


class ManualTool(PreprocessingTool):
    def __init__(self, table):
        super(ManualTool, self).__init__(table)
        pk_col = self.table.pk
        geom_col = self.table.geom
        self.sql_base = f"""select a.gid as {pk_col}_a, b.gid as {pk_col}_b
                                from {self.table.name} a, {self.table.name} b
                                where
                                    a.{geom_col} && b.{geom_col} and
                                    a.{pk_col} != b.{pk_col} and
                            """

    def find_all(self):
        self.find_self_intersection()
        self.find_overlay(tolerance=CLUSTER_TOLERANCE_R)
        self.find_multi_intersection(tolerance=CLUSTER_TOLERANCE_R)

    def find_overlay(self, tolerance):
        sql = self.sql_base + f"st_length(st_intersection(a.{self.table.geom}, st_buffer(b.{self.table.geom}, {tolerance})))>1"
        df1 = pd.read_sql(sql, conn)

        sql = f"""select a.{self.table.pk} as gid_a, b.{self.table.pk} as gid_b from {self.table.name} a, {self.table.name} b
                    where ST_overlaps(a.{self.table.geom}, b.{self.table.geom})"""
        df2 = pd.read_sql(sql, conn)

        gid_list = ManualTool.drop_duplicated(pd.concat([df1, df2]).reset_index(drop=True))
        print("重叠路段的gid：")
        print(gid_list)

    def find_multi_intersection(self, tolerance, min_dist=10):
        geom_col = self.table.geom
        pk_col = self.table.pk
        sql = self.sql_base + f"st_IsCollection(st_intersection(a.{geom_col}, st_buffer(b.{geom_col}, {tolerance})))"
        df = pd.read_sql(sql, conn)
        gid_list_temp = ManualTool.drop_duplicated(df)
        gid_list = []
        gid_list_multi = []
        for gid1, gid2 in gid_list_temp:
            sql = f"""select {geom_col} from {self.table.name} where {pk_col} in ({gid1}, {gid2})"""
            multi_intersect_gdf = geopd.read_postgis(sql, conn, geom_col=geom_col)
            geom1 = multi_intersect_gdf.loc[0, geom_col]
            geom2 = multi_intersect_gdf.loc[1, geom_col]
            intersections = geom1.intersection(geom2.buffer(tolerance))
            if intersections.geom_type not in ['MultiLineString', 'MultiPoint']:
                continue
            flag = False
            if len(intersections) >= 3:
                gid_list_multi.append((gid1, gid2))
            for i in range(len(intersections)):
                for j in range(i+1, len(intersections)):
                    if intersections[i].distance(intersections[j]) < min_dist:
                        flag = True
                        gid_list.append((gid1, gid2))
                        break
                if flag:
                    break
        print("近距离(10m内)多次相交路段的gid：")
        print(gid_list)
        print("交点数量>3的路段的gid：")
        print(gid_list_multi)

    def find_self_intersection(self):
        sql = f"select {self.table.pk} from {self.table.name} where not st_IsSimple({self.table.geom})"
        gid_list = pd.read_sql(sql, conn).values
        print("自相交：")
        print(gid_list)

    @staticmethod
    def drop_duplicated(df):
        return df.apply(ManualTool.sort_row, axis=1).drop_duplicates().values

    @staticmethod
    def sort_row(x):
        if x["gid_a"] > x["gid_b"]:
            return x["gid_b"], x["gid_a"]
        else:
            return x["gid_a"], x["gid_b"]
